import pygame,math
from task import Task

#####################################################
#                                                   #
#  Simulator Class:                                 # 
#                                                   #
#  The simulator stores information about specific  #
#  steps in a given simulation and keeps track of   #
#  which step to execute next                       #
#                                                   #
#  Author: Felix Rohrer                             #     
#  Course: CS MET 575                               #
#  Year:   2011                                     #
#                                                   #
#####################################################

class Simulator:
  def __init__(self):

    # initialize pygame
    pygame.init()

    # simulation step related variables
    self.step = None
    self.simSpeed = 1

  # execute the next step in the simulation
  # if no more next steps, return False
  def executeStep(self):
    if self.step is None:
      return False

    # if doAction returns True, then the current step has finished
    # remove this step from the simulation
    if self.step.doAction():
      self.step = None
    return True

  # insert a new step to this simulation
  def addStep(self, action, obj, toPos = (0,0)):
    s = Step(action,obj,toPos)
    self.step = s
  
  # empty all steps for this simulation 
  def empty(self):
    self.step = None

  # get object that is currently used
  def getActiveObject(self):
    if self.step is None:
      return False
    return self.step.obj

  # get phase of currently used object
  def getActiveObjectPhase(self):
    if self.step is None:
      return False
    return self.step.phase

  # set simulation speed
  def updateSimSpeed(self,upd):
    self.simSpeed = upd
    if self.step is None:
      return
    self.step.actionTime = self.simSpeed

#####################################################
#                                                   #
#  Step Class:                                      # 
#                                                   #
#  The Step class keeps the actual information for  #
#  each step of a given simulation, such as the     #
#  action to be performed.                          #
#  Currently, only the MOVE action is implemented,  #
#  which stores from where to where a given task    #
#  has to be moved.                                 #
#                                                   #
#####################################################

class Step:
  def __init__(self,action,obj, toPos = (0,0)):
    self.obj = obj # the actual object involved in this step
    self.action = action # defines this steps action
    self.actionTime = 1 # ultimately defines the speed at which the step
                        # is performed
    self.startTime = 20 # defines, how long the action is delayed in the
                        # beginning
    self.fromPos = obj.getPos()
    self.toPos = toPos

    self.speedX = 0
    self.phase = 'BEGIN'

    # indicate the time waited before the action and after the action
    self.startWaited = 0
    self.endWaited = 0

    # self.arrived checks, if x coordinate and y coordinate have reached
    # destination
    self.arrived = [False, False]

  # returns True, if this action has completely been executed
  # returns False, if this action still needs execution
  def doAction(self):
    if self.startWaited < self.startTime:
      self.startWaited +=1
    elif not self.arrived[0] or not self.arrived[1]:

      self.speed = self.actionTime

      # in the beginning of the exec phase, define the x and y direction
      # and set phase to EXEC
      if self.phase == 'BEGIN':
        # define basic speed not taking into account simulation speed
        self.dirX = self.toPos[0] - self.fromPos[0]
        self.dirY = self.toPos[1] - self.fromPos[1]

        # execution phase
        self.phase = 'EXEC'

      # find current position of the given object
      currPos = self.obj.getPos()

      # sX and sY is the movement delta in X and Y direction
      sX = 0
      sY = 0

      # decide the velocity of y direction
      if not self.arrived[0]:# and abs(currPos[0] - self.toPos[0]) > 2:
	if self.dirX >= 0 and currPos[0] >= self.toPos[0]:
	  self.arrived[0] = True
	  sX = self.toPos[0] - currPos[0]
	elif self.dirX < 0 and currPos[0] < self.toPos[0]:
	  self.arrived[0] = True
	  sX = self.toPos[0] - currPos[0]

	elif abs(self.dirX) > abs(self.speed):
	  if self.dirX > 0:
	    sX = self.speed
	  else:
	    sX = -self.speed
      else:
	self.arrived[0] = True
      
      # decide the velocity of y direction
      if not self.arrived[1]: # and (abs(currPos[1] - self.toPos[1]) > 2:
	if self.dirY >= 0 and currPos[1] >= self.toPos[1]:
	  self.arrived[1] = True
	  sY = self.toPos[1] - currPos[1]
	elif self.dirY < 0 and currPos[1] < self.toPos[1]:
	  self.arrived[1] = True
	  sY = self.toPos[1] - currPos[1]

	elif abs(self.dirY) > abs(self.speed):
	  if self.dirY > 0:
	    sY = self.speed
	  else:
	    sY = -self.speed
      else:
	self.arrived[1] = True

      currPos[0] += sX
      currPos[1] += sY

      self.obj.setPos(currPos)
    elif (self.obj.currentDS is not None and self.obj.currentDS.isExecutionUnit() and self.obj.getExecTime() > 0) \
         or self.obj.decEndTime():
      self.phase = 'END'
    else:
      # this step has completely finished (begin-exec-end)
      return True
    # this step has not yet completely finished
    return False
